package com.cdream.basic.classiccase.miaosha.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cdream.basic.classiccase.miaosha.entity.Item;
import com.cdream.basic.classiccase.miaosha.entity.ItemStock;
import com.cdream.basic.classiccase.miaosha.mapper.ItemMapper;
import com.cdream.basic.classiccase.miaosha.mapper.ItemStockMapper;
import com.cdream.basic.classiccase.miaosha.service.ItemService;
import com.cdream.basic.classiccase.miaosha.service.OrderInfoService;
import com.cdream.basic.mq.rocket.RocketMqProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zs
 * @since 2021-07-17
 */
@Service
public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements ItemService {
    @Autowired
    private ItemMapper itemMapper;
    @Autowired
    private ItemStockMapper itemStockMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private RocketMqProducer mqProducer;
    @Autowired
    private OrderInfoService orderInfoService;
    @Override
    public int increaseSales(Integer itemId, Integer amount) {
        return itemMapper.increaseSales(itemId, amount);
    }

    @Override
    public boolean decreaseStock(Integer itemId, Integer amount) {
        return itemStockMapper.decreaseStock(itemId, amount) > 0;
    }

    @Override
    @Cacheable(value = "item", key = "#itemId")
    public Item getByIdFromCache(Integer itemId) {
        return getById(itemId);
    }

    @Override
    @Transactional
    public boolean decreaseStockByRedis(Integer itemId, Integer amount) {
        if (amount == null) {
            return false;
        }
        //int affectedRow =  itemStockDOMapper.decreaseStock(itemId,amount);
        long result = redisTemplate.opsForValue().increment("promo_item_stock_" + itemId, amount.intValue() * -1);
        if (result > 0) {
            //更新库存成功
            // 如果把扣减库存放在这里或者放在主方法里都会导致下单失败情况下，扣减库存后数据库无法回滚，多扣的库存白白浪费。
            Boolean mqRes = mqProducer.asyncReduceStock(itemId, amount);
            if (!mqRes) {
                increaseStock(itemId, amount);
                return false;
            }
            return true;
        } else if (result == 0) {
            //打上库存已售罄的标识
            redisTemplate.opsForValue().set("promo_item_stock_invalid_" + itemId, "true");
            //更新库存成功
            return true;
        } else {
            //更新库存失败
            increaseStock(itemId, amount);
            return false;
        }

    }
    @Override
    @Transactional
    public boolean decreaseStockForMq(Integer itemId, Integer amount) {
        if (amount == null) {
            return false;
        }
        //int affectedRow =  itemStockDOMapper.decreaseStock(itemId,amount);
        long result = redisTemplate.opsForValue().increment("promo_item_stock_" + itemId, amount.intValue() * -1);
        if (result > 0) {
            //更新库存成功
            return true;
        } else if (result == 0) {
            //打上库存已售罄的标识
            redisTemplate.opsForValue().set("promo_item_stock_invalid_" + itemId, "true");
            //更新库存成功
            return true;
        } else {
            //更新库存失败
            increaseStock(itemId, amount);
            return false;
        }

    }

    @Override
    public void publishPromo(Integer itemId) {
        QueryWrapper<ItemStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("item_id",itemId);
        ItemStock itemStock = itemStockMapper.selectOne(queryWrapper);
        if (itemStock==null){
            throw new RuntimeException("该商品不存在");
        }
        //将库存同步到redis内
        redisTemplate.opsForValue().set("promo_item_stock_"+itemId, itemStock.getStock());

        //将大闸的限制数字设到redis内
        // redisTemplate.opsForValue().set("promo_door_count_"+promoId,itemStock.getStock().intValue() * 5);

    }

    @Override
    public boolean increaseStock(Integer itemId, Integer amount) {
        redisTemplate.opsForValue().increment("promo_item_stock_" + itemId, amount.intValue());
        return true;
    }
    @Transactional
    @Override
    public void testMysql(){
        Item item = getById(6);
        item.setPrice(new BigDecimal("8"));
        updateById(item);
        orderInfoService.realUpdate(item);
    }




}
